﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using MentalAlchemy.Molecules;
using MentalAlchemy.Molecules.Image;

namespace MentalAlchemy.Compounds.Image
{
	public partial class ImageCategoryTableControl : UserControl
	{
		#region - Variable. -
		private List<SparseImageDescription> descrs = new List<SparseImageDescription>();
		#endregion

		#region - Properties. -
		/// <summary>
		/// Number of data grid entries.
		/// </summary>
		public int Count
		{
			get { return dataGrid.Rows.Count; }
		}

		/// <summary>
		/// Returns previously loaded descriptions.
		/// </summary>
		public List<SparseImageDescription> Descriptions
		{
			get { return descrs; }
		}

		/// <summary>
		/// Forms information about known categories for data grid entries.
		/// </summary>
		public Dictionary<string, string> CategoryInfo
		{
			get
			{
				var res = new Dictionary<string, string>();

				foreach (DataGridViewRow row in dataGrid.Rows)
				{
					if (row.Cells[0].Value == null || row.Cells[1].Value == null) continue;

					res.Add(row.Cells[0].Value.ToString(), row.Cells[1].Value.ToString());
				}

				return res;
			}
		}

		/// <summary>
		/// Gets or sets visibility status for "Add image..." button.
		/// </summary>
		public bool ShowAddImageButton
		{
			get { return AddImage.Visible; }
			set { AddImage.Visible = value; }
		}

		/// <summary>
		/// Gets or sets visibility status for "Load cats info..." button.
		/// </summary>
		public bool ShowLoadCatInfoButton
		{
			get { return LoadCatInfoBtn.Visible; }
			set { LoadCatInfoBtn.Visible = value; }
		}

		/// <summary>
		/// Gets or sets visibility status for "Load descriptions..." button.
		/// </summary>
		public bool ShowLoadDescriptionsButton
		{
			get { return LoadDescrBtn.Visible; }
			set { LoadDescrBtn.Visible = value; }
		}
		#endregion

		#region - Constructor. -
		public ImageCategoryTableControl()
		{
			InitializeComponent();
		} 
		#endregion

		#region - Event Handlers. -
		private void AddImage_Click(object sender, EventArgs e)
		{
			openFileDialog1.Filter = Const.IMAGE_FILE_FILTER;
			var res = openFileDialog1.ShowDialog();

			if (res == DialogResult.OK)
			{
				var files = openFileDialog1.FileNames;
				AddFiles(files);
			}
		}

		private void LoadDescrBtn_Click(object sender, EventArgs e)
		{
			openFileDialog1.Filter = "";
			var res = openFileDialog1.ShowDialog();

			if (res == DialogResult.OK)
			{
				foreach (var fileName in openFileDialog1.FileNames)
				{
					AddDescriptions(fileName);
				}
			}
		}

		private void LoadCatInfoBtn_Click(object sender, EventArgs e)
		{
			openFileDialog1.Filter = "";
			var res = openFileDialog1.ShowDialog();

			if (res == DialogResult.OK)
			{
				//
				// This method awaits files with the following structure:
				//
				//	<filename><TAB>[<category name>]
				//
				//	where <category name> is optional.
				//
				foreach (var fileName in openFileDialog1.FileNames)
				{
					AddCategories(fileName);
				}
			}
		}

		private void ClearBtn_Click(object sender, EventArgs e)
		{
			dataGrid.Rows.Clear();
			descrs.Clear();
		}
		#endregion

		#region - Public methods. -
		/// <summary>
		/// Adds given files to the data grid.
		/// </summary>
		/// <param name="files">Array of filenames.</param>
		public void AddFiles(string[] files)
		{
			foreach (var file in files)
			{
				var row = GetRowByFilename(file);
				if (row == null)
				{
					dataGrid.Rows.Add(file);
				}
			}
		} 

		/// <summary>
		/// Adds descriptions from the given file to the data grid.
		/// </summary>
		/// <param name="file">Filename for the list of [SparseImageDescription] elements.</param>
		public void AddDescriptions (string file)
		{
			var tempDescrs = ImageDescriptionElements.Deserialize(file);
			
			var files = new List<string>();
			foreach (var descr in tempDescrs)
			{
				files.Add(descr.ImageName);
			}
			AddFiles(files.ToArray());

			descrs.AddRange(tempDescrs);
		}

		/// <summary>
		/// Adds categories for previously loaded image descriptions.
		///
		/// This method awaits files with the following structure:
		///
		///	<filename><TAB><category name>
		///
		///	where <category name> is optional.
		///
		/// </summary>
		/// <param name="fileName"></param>
		public void AddCategories (string fileName)
		{
			var lines = FileIO.ReadColumns(fileName, null);

			foreach (var line in lines)
			{
				var row = GetRowByFilename(line[0]);
				if (row != null && line.Length > 1)
				{
					row.Cells[1].Value = line[1];
				}
				else
				{	// add a new row.
					if (line.Length > 1)
					{
						dataGrid.Rows.Add(line[0], line[1]);
					}
					else
					{	// if category is not specified, then add a filename only.
						dataGrid.Rows.Add(line[0]);
					}
				}
			}
		}

		/// <summary>
		/// Checks whether data grid has a row with a given filename.
		/// </summary>
		/// <param name="file"></param>
		/// <returns></returns>
		public DataGridViewRow GetRowByFilename (string file)
		{
			var shortFile = FileIO.GetShortRelativePath(file);
			foreach (DataGridViewRow row in dataGrid.Rows)
			{
				if (row.IsNewRow) continue;

				var rowFilename = (string)row.Cells[0].Value;
				var shortRowFile = FileIO.GetShortRelativePath(rowFilename);

				if (string.Compare(shortRowFile, shortFile, true) == 0) return row;
			}
			return null;
		}
		#endregion
	}
}
